package com.ruoyi.common.utils;

import org.apache.commons.compress.utils.Lists;
import org.opencv.core.*;
import org.opencv.features2d.*;
import org.opencv.imgcodecs.Imgcodecs;

import java.io.File;
import java.nio.file.*;
import java.util.*;
import java.io.IOException;

public class ImageDuplicateDetector {

    static {
        System.load("D:\\Program Files\\opencv\\build\\java\\x64\\opencv_java490.dll");
    }

    private static final ORB orb = ORB.create();
    private static final BFMatcher matcher = BFMatcher.create(Core.NORM_HAMMING, true);

    public static List<String> findDuplicateImages(String folderPath) throws IOException {
        Map<Mat, String> imageFeatures = new HashMap<>();
        List<String> pathList = Lists.newArrayList();
        Files.walk(Paths.get(folderPath)).forEach(filePath -> {
            if (Files.isRegularFile(filePath)) {
                Mat img = Imgcodecs.imread(filePath.toString(), Imgcodecs.IMREAD_GRAYSCALE);
                if (img.empty()) return;

                MatOfKeyPoint keyPoints = new MatOfKeyPoint();
                Mat descriptors = new Mat();
                orb.detectAndCompute(img, new Mat(), keyPoints, descriptors);

                if (descriptors.empty()) {
                    System.out.println("No descriptors found for image: " + filePath);
                    return;
                }

                boolean isDuplicate = false;
                for (Map.Entry<Mat, String> entry : imageFeatures.entrySet()) {
                    double similarity = calculateSimilarity(descriptors, entry.getKey());
                    if (similarity > 0.75) {
                        System.out.println("Duplicate image found: " + filePath +
                                " is similar to " + entry.getValue());
                        isDuplicate = true;
                        pathList.add(filePath.toString());

                        break;
                    }
                }

                if (!isDuplicate) {
                    imageFeatures.put(descriptors, filePath.toString());
                }
            }
        });
        return pathList;
    }

    // 计算两张图片描述符的相似性
    private static double calculateSimilarity(Mat descriptors1, Mat descriptors2) {
        MatOfDMatch matches = new MatOfDMatch();
        matcher.match(descriptors1, descriptors2, matches);

        List<DMatch> matchList = matches.toList();  // 将 MatOfDMatch 转换为 List<DMatch>
        int goodMatches = 0;
        for (DMatch match : matchList) {
            if (match.distance < 30) {  // 调整距离阈值
                goodMatches++;
            }
        }

        return (double) goodMatches / matchList.size();
    }

    public static void delImage(List<String> pathList){
        for(String path:pathList){
            File file = new File(path);
            file.delete();
        }
    }

    public static void moveImageToFolder(String sourceFilePath, String targetFolderPath) {
        Path sourcePath = Paths.get(sourceFilePath);
        Path targetDir = Paths.get(targetFolderPath);

        // 确保目标文件夹存在，如果不存在则创建
        if (!Files.exists(targetDir)) {
            try {
                Files.createDirectories(targetDir);
            } catch (IOException e) {
                System.err.println("无法创建目标文件夹: " + targetFolderPath);
                e.printStackTrace();
                return;
            }
        }

        // 确定目标文件的路径
        Path targetPath = targetDir.resolve(sourcePath.getFileName());

        try {
            // 将文件移动到目标文件夹，覆盖已存在的文件
            Files.move(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING);
            System.out.println("文件已移动到: " + targetPath);
        } catch (IOException e) {
            System.err.println("移动文件失败: " + sourceFilePath + " -> " + targetFolderPath);
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        String folderPath = "D:\\material\\Materialflow\\shoudi";

        try {
            List<String> pathList = findDuplicateImages(folderPath);
            delImage(pathList);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


